package alingrad.engine.graphics;

import java.util.ArrayList;
import java.util.LinkedList;

import alingrad.engine.core.GameRenderer;
import alingrad.engine.util.GLColor;
import alingrad.engine.util.ObjectPool;

public class RenderManager {
	private static final int MAX_RENDER_PER_FRAME = 256;

	private ArrayList<LinkedList<RenderListNode>> mRenderLists;
	private RenderListNodePool mNodePool;
	private final GameRenderer mRenderer;
	private int mRenderListIndex;

	public RenderManager(final GameRenderer renderer) {
		mRenderer = renderer;
		mRenderListIndex = 0;
		mRenderLists = new ArrayList<LinkedList<RenderListNode>>(2);
		mNodePool = new RenderListNodePool(MAX_RENDER_PER_FRAME * 2);
		for (int i = 0; i < 2; i++)
			mRenderLists.add(new LinkedList<RenderListNode>());
	}

	public void setBackgroundColor(final GLColor color) {
		mRenderer.setBackgroundColor(color);
	}

	public void scheduleToRender(final Renderable object, final GLColor color) {
		scheduleToRender(object, 0f, 0f, 0f, 1f, 1f, color);
	}

	public void scheduleToRender(final Renderable object, final float x, final float y, final GLColor color) {
		scheduleToRender(object, x, y, 0f, 1f, 1f, color);
	}

	public void scheduleToRender(final Renderable object, final float x, final float y, final float rotation, final GLColor color) {
		scheduleToRender(object, x, y, rotation, 1f, 1f, color);
	}

	public void scheduleToRender(final Renderable object, final float x, final float y, final float rotation, final float scaleX, final float scaleY, final GLColor color) {
		RenderListNode node = mNodePool.allocate();
		node.set(object, x, y, rotation, scaleX, scaleY, color);
		mRenderLists.get(mRenderListIndex).add(node);
	}

	public void sync() {
		mRenderer.setRenderList(mRenderLists.get(mRenderListIndex));

		mRenderListIndex = (mRenderListIndex + 1) % 2;
		emptyList(mRenderLists.get(mRenderListIndex));
	}

	private void emptyList(LinkedList<RenderListNode> list) {
		for (int i = 0; i < list.size(); i++)
			mNodePool.release(list.remove());
	}

	private class RenderListNodePool extends ObjectPool<RenderListNode> {

		public RenderListNodePool(int size) {
			super(size);
		}

		@Override
		public RenderListNode construct() {
			return new RenderListNode();
		}

	}
}
